package sistema;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.List;

import model.Publicacion.Pregunta;
import model.Publicacion.Respuesta;
import model.Usuario.UsuarioModerador;
import model.Usuario.UsuarioNoRegistrado;
import model.Usuario.UsuarioSimple;
import model.criterio.criteriosYbusqueda.BusquedaDePreguntas;
import model.criterio.criteriosYbusqueda.Criterio;
import model.criterio.criteriosYbusqueda.CriterioDeAutor;
import model.criterio.criteriosYbusqueda.CriterioDeEtiquetas;
import model.insigniaYlogros.Insignia;
import model.insigniaYlogros.InsigniaSimple;
import model.sistema.Sistema;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class TestSistema {
	
	Sistema sistema;
	UsuarioNoRegistrado usuarioN;
	UsuarioSimple usuarioS;
	UsuarioModerador usuarioM;
	Pregunta p;
	Respuesta r;
	Pregunta p1;
	Respuesta r1;
	List<Pregunta> l;
	List<Pregunta> l1;
	List<Pregunta> l2;
	
	List<Respuesta> l3;
	List<Respuesta> l4;
	List<Respuesta> l5;
	
	Insignia ins;
	
	Criterio c1;
	Criterio c2;
	
	@Before
	public void setUp()
	{
		sistema =new Sistema();
		usuarioN=mock(UsuarioNoRegistrado.class);
		usuarioM=mock(UsuarioModerador.class);
		usuarioS=mock(UsuarioSimple.class);
		sistema.registrarUsuario(usuarioM);
		sistema.registrarUsuario(usuarioN);
		sistema.registrarUsuario(usuarioS);
		p=mock(Pregunta.class);
		r=mock(Respuesta.class);
		p1=mock(Pregunta.class);
		r1=mock(Respuesta.class);
		l=new ArrayList<Pregunta>();
		l1=new ArrayList<Pregunta>();
		l2=new ArrayList<Pregunta>();
		l3=new ArrayList<Respuesta>();
		l4=new ArrayList<Respuesta>();
		l5=new ArrayList<Respuesta>();
		ins=mock(InsigniaSimple.class);
		
		c1=mock(CriterioDeEtiquetas.class);
		c2=mock(CriterioDeAutor.class);
		
	}
	@Test
	public void testAgregarUsuarioAlSistema()
	{
		Integer cantidadEsperada1=0;
		Assert.assertEquals(cantidadEsperada1, sistema.cantidadDePreguntas());
		Assert.assertEquals(cantidadEsperada1, sistema.cantidadDeRespuestas());
		Integer cantidadEsperadaUs1=3;
		Assert.assertEquals(cantidadEsperadaUs1, sistema.cantidadDeUsuarios());
		l.add(p);
		l2.add(p1);
		l4.add(r);
		l5.add(r1);
		when(usuarioS.getRespuestas()).thenReturn(l3);
		when(usuarioN.getRespuestas()).thenReturn(l4);
		when(usuarioM.getRespuestas()).thenReturn(l5);
		when(usuarioS.getPreguntas()).thenReturn(l);
		when(usuarioM.getPreguntas()).thenReturn(l2);
		sistema.agregarUsuario(usuarioS);
		sistema.agregarUsuario(usuarioM);
		
		
		verify(usuarioM,times(1)).getPreguntas();
		verify(usuarioS,times(1)).getPreguntas();
		
		verify(usuarioM,times(1)).getRespuestas();
		
		verify(usuarioS,times(1)).getRespuestas();
		
		Integer cantidadEsperada=2;
		Integer cantidadEsperadaF=1;
		Assert.assertEquals(cantidadEsperada, sistema.cantidadDePreguntas());
		Assert.assertEquals(cantidadEsperadaF, sistema.cantidadDeRespuestas());
		Integer cantidadEsperadaUs=5;
		Assert.assertEquals(cantidadEsperadaUs, sistema.cantidadDeUsuarios());
		
		Assert.assertEquals(true, sistema.tieneA(usuarioM));
		Assert.assertEquals(true, sistema.tieneA(usuarioN));
		Assert.assertEquals(true, sistema.tieneA(usuarioS));
		
	
		
		
	}
	@Test
	public void testAgregarPregunta()
	{
		sistema.agregarPregunta(p);
		Integer cantEsperada1=1;
		Integer cantEsperada2=2;
		Assert.assertEquals(cantEsperada1, sistema.cantidadDePreguntas());
		sistema.agregarPregunta(p1);
		Assert.assertEquals(cantEsperada2, sistema.cantidadDePreguntas());
	}
	@Test
	public void testAgregarRespuesta()
	{
		sistema.agregarRespuesta(r);
		Integer cantEsperada1=1;
		Integer cantEsperada2=2;
		Assert.assertEquals(cantEsperada1, sistema.cantidadDeRespuestas());
		sistema.agregarRespuesta(r1);
		Assert.assertEquals(cantEsperada2, sistema.cantidadDeRespuestas());
	}
	@Test
	public void testEliminarPregunta()
	{
		sistema.agregarPregunta(p);
		Integer cantEsperada1=1;
		Integer cantEsperada2=2;
		Assert.assertEquals(cantEsperada1, sistema.cantidadDePreguntas());
		sistema.agregarPregunta(p1);
		Assert.assertEquals(cantEsperada2, sistema.cantidadDePreguntas());
		sistema.eliminarPregunta(p);
		when(p.estaEliminada()).thenReturn(true);
		verify(p,times(1)).eliminar();
		Assert.assertEquals(1, sistema.cantidadDePreguntasEliminadas());
		sistema.eliminarPregunta(p1);
		when(p1.estaEliminada()).thenReturn(true);
		verify(p1,times(1)).eliminar();
		Assert.assertEquals(2, sistema.cantidadDePreguntasEliminadas());
		Integer cantFinal=0;
		Assert.assertEquals(cantFinal,sistema.cantidadDePreguntas());
		
	}
	@Test
	public void testEliminarRespuesta()
	{
		sistema.agregarRespuesta(r);
		Integer cantEsperada1=1;
		Integer cantEsperada2=2;
		Assert.assertEquals(cantEsperada1, sistema.cantidadDeRespuestas());
		sistema.agregarRespuesta(r1);
		Assert.assertEquals(cantEsperada2, sistema.cantidadDeRespuestas());
		sistema.eliminarRespuesta(r);
		when(r.estaEliminada()).thenReturn(true);
		verify(r,times(1)).eliminar();
		Assert.assertEquals(1, sistema.cantidadDeRespuestasEliminadas());
		sistema.eliminarRespuesta(r1);
		when(r1.estaEliminada()).thenReturn(true);
		verify(r1,times(1)).eliminar();
		Assert.assertEquals(2, sistema.cantidadDeRespuestasEliminadas());
		Integer cantEspF=0;
		Assert.assertEquals(cantEspF,sistema.cantidadDeRespuestas());
	}
	@Test
	public void testActualizarInsignias()
	{
		sistema.agregarInsignia(ins);
		
		when(ins.seCumple(usuarioS)).thenReturn(true);
		when(usuarioS.noContieneInsignia(ins)).thenReturn(true);
		sistema.actualizarInsigniasPara(usuarioS);
		
		verify(usuarioS,times(1)).noContieneInsignia(ins);
		verify(usuarioS,times(1)).agregarInsignia(ins);
		verify(ins,times(1)).seCumple(usuarioS);
		
		Assert.assertEquals(1, sistema.cantidadDeInsignias());
		
		when(ins.seCumple(usuarioS)).thenReturn(false);
		when(usuarioS.noContieneInsignia(ins)).thenReturn(false);
		sistema.actualizarInsigniasPara(usuarioS);
		
		verify(usuarioS,times(2)).noContieneInsignia(ins);
		verify(ins,times(2)).seCumple(usuarioS);
		
		Assert.assertEquals(1, sistema.cantidadDeInsignias());
		
	}
	@Test
	public void testInciarBusquedaDePregunta()
	{
		BusquedaDePreguntas b=sistema.iniciarBusquedaDePreguntasCon(c1,c2);
		Assert.assertEquals(2,b.getCantCriterios());
		Assert.assertEquals(sistema.getPreguntas(),b.getPreguntas());
	}

	
}
